home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Info-Mac 4
/
Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso
/
Development
/
Source
/
Telnet 2.6.1d1 4⁄26⁄94 Folder
/
Krb
/
kerberos.c
< prev
next >
Wrap
Text File
|
1994-02-20
|
8KB
|
328 lines
/*
* kerberos.c
*/
#ifdef MPW
#pragma segment 22
#endif
#define NCSA_ENC
#ifdef TN3270
#pragma segment 3270tcp
#if !defined(USEDUMP)
#include "maclib.h"
#include "termdef.h"
#include "tn3270funcs.h"
#include "globals.h"
#else
#pragma load "tn3270DumpFile"
#endif
#include "telnet.h"
#include "hostform.h"
#endif /* TN3270 */
#ifdef NCSA_ENC
#include <String.h>
#include "TelnetHeader.h"
#include "wind.h"
#include "parse.proto.h"
#endif
#define TELCMDS 1
#define TELOPTS 1
#include "encrypt.proto.h"
#include "kerberos.proto.h"
#include "desproto.h"
static short kdriver = 0; /* .Kerberos driver ref */
/*
* krb_telnet
* Send Kerberos credentials as a telnet suboption.
* Return error number if error;
*
* Called with doit==false to verify that we have
* enough credentials.
*/
long krb_telnet (WDATA *cr, char *tp, long doit)
{
#pragma unused (doit)
long i, len;
short s;
unsigned char *cp, *cn, cannon[256];
ParamBlockRec pbr, *pb = &pbr;
krbHiParmBlock khpb, *khipb = &khpb;
krbParmBlock klpb, *klopb = &klpb;
unsigned char buf[1258+20];
Session_Key skey;
Str255 scratch1, scratch2, kname;
unsigned char *kp;
des_cblock sessionKey;
/*
* Open the .Kerberos driver if not already open
*/
if (!kdriver) {
if (s = OpenDriver("\p.Kerberos", &kdriver)) {
return -1;
}
}
/*
* Figure out the cannonical hosthame.
* If we used domain lookup, it should be in mp->cannon.
* Otherwise, we use mp->hname.
*/
cp = 0;
cp = (unsigned char *)getcname(cr);
if (!cp)
return -1;
/*
* Get the realm of the host
*/
strcpy((char *)scratch2, (char *)cp);
if (scratch2[strlen((char *)scratch2)-1] == '.')
scratch2[strlen((char *)scratch2)-1] = '\0';
xbzero(klopb, sizeof(*klopb));
klopb->host = (char *)scratch2;
klopb->uRealm = (char *)scratch1;
if (s = lowcall(cKrbGetRealm, klopb, kdriver))
return -1;
/*
* build rcmd.hostname@realm
*/
strcpy((char *)cannon, "rcmd.");
cn = &cannon[5];
strncpy((char *)cn, (char *)cp, sizeof(cannon)-5);
cannon[sizeof(cannon)-1] = '\0';
if (cp = (unsigned char *)strchr((char *)cn, '.'))
*cp = '\0';
strcat((char *)cannon, "@");
strcat((char *)cannon, (char *)scratch1);
/*
* use cKrbGetAuthForService to get auth data for telnet option
*
* Similiar to cKrbGetTicketForService except it builds a kerberos "SendAuth" style
request (with SendAuth and application version numbers preceeding the actual ticket)
-> service Formal Kerberos name of service
-> buf Buffer to receive ticket
-> checksum checksum for this service
<-> buflen length of ticket buffer (must be at least 1258 bytes)
<- sessionKey for internal use
<- schedule for internal use
*/
xbzero(khipb, sizeof(krbHiParmBlock));
khipb->service = (char *)cannon;
khipb->buf = (char *)buf; /* where to build it */
khipb->checksum = 0;
khipb->buflen = sizeof(buf);
if (s = hicall(cKrbGetTicketForService, khipb, kdriver))
return s;
xbcopy(khipb->sessionKey, sessionKey, sizeof(sessionKey)); /* save the session key */
/*
* cKrbGetTicketForService put a longword buffer length into the buffer
* which we don't want, so we ignore it.
* Make room for first 3 bytes which preceed the auth data.
*/
cp = &buf[4-3]; /* skip long, make room for 3 bytes */
cp[0] = tp[0]; /* copy type and modifier */
cp[1] = tp[1];
cp[2] = KRB_AUTH; /* suboption command */
len = khipb->buflen - sizeof(long) + 3; /* data - 4 + 3 */
xbzero(khipb, sizeof(krbHiParmBlock)); /* get kerberos user name */
khipb->user = (char *)kname;
if (s = hicall(cKrbGetUserName, khipb, kdriver))
return s;
if (kp = (unsigned char *)strchr((char *)kname, '@'))
*kp = '\0';
tn_sendsub(cr, OPT_AUTHENTICATION, TNQ_NAME, (char *)kname, strlen((char *)kname));
tn_sendsub(cr, OPT_AUTHENTICATION, TNQ_IS, (char *)cp, len);
/*
* If we are going to do mutual authentication, go ahead and
* generate the challenge and response here so we won't have to figure
* out the credentials again later.
*/
if (tp[1] & AUTH_HOW_MUTUAL) {
unsigned char challenge[8];
des_key_schedule sched;
des_init_random_number_generator(sessionKey);
des_key_sched(sessionKey, sched);
des_set_random_generator_seed((des_cblock *)sessionKey);
des_new_random_key(challenge);
des_ecb_encrypt((unsigned long *)challenge, (unsigned long *)cr->auth_challenge, sched, 1);
skey.type = SK_DES; /* save key for ENCRYPT */
skey.length = 8;
skey.data = (unsigned char *)cr->auth_challenge;
encrypt_session_key(cr->edata, &skey, 0);
/*
* Increment the challenge by 1, and encrypt it for
* later comparison.
*/
for (i = 7; i >= 0; --i) {
register long x;
x = (unsigned long)challenge[i] + 1;
challenge[i] = x; /* ignore overflow */
if (x < 256) /* if no overflow, all done */
break;
}
des_ecb_encrypt((unsigned long *)challenge, (unsigned long *)cr->auth_response, sched, 1);
skey.type = SK_DES; /* save key for ENCRYPT */
skey.length = 8;
skey.data = (unsigned char *)cr->auth_response;
encrypt_session_key(cr->edata, &skey, 1);
}
return 0;
}
/*
* tn_kerberos_reply
* Process a AUTHENTICATION REPLY of type KRBEROS_V4.
*/
void tn_kerberos_reply (WDATA *tw, unsigned char *subbuffer)
{
switch (subbuffer[SB_DATATYPE] & 0xff) {
case KRB_AUTH:
break;
case KRB_REJECT:
break;
case KRB_ACCEPT:
/*
* If mutual authentication, it is time to send the challenge.
*/
if (subbuffer[SB_MODIFIER] & AUTH_HOW_MUTUAL)
tn_send_challenge(tw, subbuffer);
break;
case KRB_CHALLENGE:
break;
case KRB_RESPONSE:
/*
* We got a response to an authorization challenge. Make
* sure it is the correct response.
*/
#ifdef notdef /* ... ??? */
if (xbcmp(&subbuffer[SB_DATA], tw->auth_response, 8))
/*
* ??? What do we do here? -- presumably clear the connection.
*/
printf("\n[Challenge failed]\n");
else
printf("\n[Challenge succeeded]\n");
#endif
break;
}
}
/*
* tn_send_challenge
* Send a challenge
*/
void tn_send_challenge (WDATA *tw, unsigned char *subbuffer)
{
char buf[2+1+8];
buf[0] = subbuffer[SB_TYPE];
buf[1] = subbuffer[SB_MODIFIER];
buf[2] = KRB_CHALLENGE;
xbcopy(tw->auth_challenge, &buf[3], 8);
tn_sendsub(tw, OPT_AUTHENTICATION, TNQ_IS, buf, sizeof(buf));
}
short lowcall (long cscode, krbParmBlock *klopb, short kdriver)
{
short s;
ParamBlockRec pb;
xbzero(&pb, sizeof(ParamBlockRec));
*(long *)pb.cntrlParam.csParam = (long)klopb;
pb.cntrlParam.ioCompletion = nil;
pb.cntrlParam.ioCRefNum = kdriver;
pb.cntrlParam.csCode = cscode;
if (s = PBControl(&pb, false))
return s;
if (s = pb.cntrlParam.ioResult)
return s;
return 0;
}
short hicall (long cscode, krbHiParmBlock *khipb, short kdriver)
{
short s;
ParamBlockRec pb;
xbzero(&pb, sizeof(ParamBlockRec));
*(long *)pb.cntrlParam.csParam = (long)khipb;
pb.cntrlParam.ioCompletion = nil;
pb.cntrlParam.ioCRefNum = kdriver;
pb.cntrlParam.csCode = cscode;
if (s = PBControl(&pb, false))
return s;
if (s = pb.cntrlParam.ioResult)
return s;
return 0;
}
/*
* bcopy
* Block copy
*/
void xbcopy (void *src, void *dst, long n)
{
long i;
register unsigned char *s = src;
register unsigned char *d = dst;
for (i = 0; i < n; i++)
*d++ = *s++;
}
/*
* bcmp
* return 0 if blocks compare ok
*/
long xbcmp (void *src, void *dst, long n)
{
register char *s = src;
register char *d = dst;
while (n-- > 0)
if (*s++ != *d++)
return 1;
return 0;
}
/*
* bzero
* Block zero
*/
void xbzero (void *dst, long n)
{
register char *d = dst;
while (n--)
*d++ = 0;
}